#include "..\\stdafx.h"
#include "PyrometerDiv.h"
#include "FCDraw.h"
#include "..\\Service\\DataCenter.h"
#include <Urlmon.h>
#pragma comment(lib, "Urlmon.lib")

PyrometerDiv::PyrometerDiv(){
    INF = 0x3f3f3f;
    Rwidth = 0;
    Rheight = 0;
    m_tick = 0;
    m_timerID = FCView::getNewTimerID();
    m_useAnimation = false;
}

PyrometerDiv::~PyrometerDiv(){
}

int PyrometerDiv::getWIDTH(){
    return getWidth();
}

int PyrometerDiv::getHEIGHT(){
    return getHeight();
}

int PyrometerDiv::get_WIDTH(){
    return getWidth();
}

int PyrometerDiv::get_HEIGHT(){
    return getHeight();
}

void PyrometerDiv::layoutrow(ArrayList<double> R, double w)
{
    double lx = getWIDTH() - Rwidth + (get_WIDTH() - getWIDTH()) / 2.0;
    double ly = getHEIGHT() - Rheight + (get_HEIGHT() - getHEIGHT()) / 2.0;  

    int direction;  // 0: horizontal;  1: vertical

    double sum = 0;
    for(int x = 0; x < R.size(); x++)
    {
        sum += R.get(x);
    }
    double ext = sum / w;
    if (abs(w - Rwidth) <= 1e-6)
    {
        Rheight -= ext;
        direction = 0;
    }
    else
    {
        Rwidth -= ext;
        direction = 1;
    }

    for(int x = 0; x < R.size(); x++)
    {
        double r = R.get(x);
        if (direction == 0)
        {
            double hh = ext, ww = r / ext;
            FCRectF newRect;
			newRect.left = floor(lx);
            newRect.top = floor(ly);
            newRect.right = ceil(lx + ww);
            newRect.bottom = ceil(ly + hh);
            m_rects.add(newRect);
            lx += ww;
        }
        else
        {
            double ww = ext, hh = r / ext;
            FCRectF newRect;
            newRect.left = floor(lx);
            newRect.top = floor(ly);
            newRect.right = ceil(lx + ww);
            newRect.bottom = ceil(ly + hh);
            m_rects.add(newRect);
            ly += hh;
        }
    }
}

double PyrometerDiv::width(ArrayList<double> R, int w)
{
    return FCTran::minValue(Rwidth, Rheight);
}

double PyrometerDiv::worst(ArrayList<double> R, double w)
{
    if (R.size() == 0) return INF;
    double rmx = 0, rmn = INF, s = 0;
    for(int x = 0; x < R.size(); x++)
    {
        double r = R.get(x);
        s += r;
        if (r > rmx) rmx = r;
        if (r < rmn) rmn = r;
    }
    double pw = pow(w, 2), sw = pow(s, 2);
    double res = FCTran::maxValue(pw * rmx / sw, sw / (pw * rmn));
    return FCTran::maxValue(pw * rmx / sw, sw / (pw * rmn));
}

void PyrometerDiv::onAdd(){
    FCDiv::onAdd();
    startTimer(m_timerID, 10);
	if (m_datas.size() == 0)
    {
		String url = L"http://110.42.188.197:9968/quote?func=price&count=100&codes=all";
		String guid = FCTran::stringToString(DataCenter::getGuid());
		String tempFile = DataCenter::getAppPathW() + L"\\" + guid;
		BOOL bSuccess = ::URLDownloadToFile(0, url.c_str(), tempFile.c_str(), 0, 0);
		if(FCFile::isFileExist(tempFile)){
			int fileLength = FCFile::getFileLength(FCTran::StringTostring(tempFile).c_str());
			char *szContent = new char[fileLength + 1];
			memset(szContent, '\0', fileLength + 1);
			std::ifstream fs(FCTran::StringTostring(tempFile).c_str(), std::ios::in); 
			if(fs){
				if(fileLength > 0){
					while(!fs.eof()){
						fs.read(szContent, fileLength); 
					}
				}
				fs.close();
			}
			std::string uResult;
			StrCoding::UTF_8ToGB2312(uResult, szContent);
			delete[] szContent;
			szContent = 0;
			String result = FCTran::stringToString(uResult.c_str());
			FCFile::removeFile(tempFile);
			ArrayList<String> strs = FCTran::split(result, L"\n");
            for (int i = 0; i < strs.size(); i++)
            {
                ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
                if (subStrs.size() >= 15)
                {
					PriceData2 priceData;
                    priceData.m_key = subStrs.get(0);
                    priceData.m_text = subStrs.get(1);
					priceData.m_value = FCTran::strToDouble(subStrs.get(6));
					priceData.m_close = FCTran::strToDouble(subStrs.get(2));
					priceData.m_lastClose = FCTran::strToDouble(subStrs.get(8));
					if(priceData.m_value > 0){
						m_datas.add(priceData);
					}
                }
            }
		}
	}
	updatePyromoter();
}

void PyrometerDiv::onRemove(){
    FCDiv::onRemove();
    stopTimer(m_timerID);
}

bool PriceDataCompare(PriceData2 x, PriceData2 y){
    if(x.m_value > y.m_value){
        return 1;
    }else{
        return 0;
    }
}

void PyrometerDiv::onTimer(int timerID){
    FCDiv::onTimer(timerID);
   if (timerID == m_timerID)
   {
       m_tick++;
       if (m_tick > 1000000)
       {
           m_tick = 0;
       }
       bool paint2 = false;
       if (m_useAnimation)
        {
           for (int i = 0; i < m_rects.size() && i < m_datas.size(); i++)
           {
               FCRectF targetRect = m_rects.get(i);
               PriceData2 priceData = m_datas.get(i);
               FCRectF nowRect = priceData.m_nowRect;
               if (true)
               {
                   if (nowRect.left > targetRect.left)
                   {
                       nowRect.left -= (nowRect.left - targetRect.left) / 4;
                       if (nowRect.left - targetRect.left < 10)
                       {
                           nowRect.left = targetRect.left;
                       }
                       paint2 = true;
                   }
                   else if (nowRect.left < targetRect.left)
                   {
                       nowRect.left += (targetRect.left - nowRect.left) / 4;
                       if (targetRect.left - nowRect.left < 10)
                       {
                           nowRect.left = targetRect.left;
                       }
                       paint2 = true;
                   }
               }

               if (true)
               {
                   if (nowRect.top > targetRect.top)
                   {
                       nowRect.top -= (nowRect.top - targetRect.top) / 4;
                       if (nowRect.top - targetRect.top < 10)
                       {
                           nowRect.top = targetRect.top;
                       }
                       paint2 = true;
                   }
                   else if (nowRect.top < targetRect.top)
                   {
                       nowRect.top += (targetRect.top - nowRect.top) / 4;
                       if (targetRect.top - nowRect.top < 10)
                       {
                           nowRect.top = targetRect.top;
                       }
                       paint2 = true;
                   }
               }

               if (true)
               {
                   if (nowRect.right > targetRect.right)
                   {
                       nowRect.right -= (nowRect.right - targetRect.right) / 4;
                       if (nowRect.right - targetRect.right < 10)
                       {
                           nowRect.right = targetRect.right;
                       }
                       paint2 = true;
                   }
                   else if (nowRect.right < targetRect.right)
                   {
                       nowRect.right += (targetRect.right - nowRect.right) / 4;
                       if (targetRect.right - nowRect.right < 10)
                       {
                           nowRect.right = targetRect.right;
                       }
                       paint2 = true;
                   }
               }
               if (true)
               {
                   if (nowRect.bottom > targetRect.bottom)
                   {
                       nowRect.bottom -= (nowRect.bottom - targetRect.bottom) / 4;
                       if (nowRect.bottom - targetRect.bottom < 10)
                       {
                           nowRect.bottom = targetRect.bottom;
                       }
                       paint2 = true;
                   }
                   else if (nowRect.bottom < targetRect.bottom)
                   {
                       nowRect.bottom += (targetRect.bottom - nowRect.bottom) / 4;
                       if (targetRect.bottom - nowRect.bottom < 10)
                       {
                           nowRect.bottom = targetRect.bottom;
                       }
                       paint2 = true;
                   }
               }
               priceData.m_nowRect = nowRect;
               m_datas.set(i, priceData);
           }
        }
       if (paint2)
       {
           invalidate();
       }
   }
}

void PyrometerDiv::onPaint(FCPaint *paint, const FCRect& clipRect){
    FCDiv::onPaint(paint, clipRect);
	int width = getWidth(), height = getHeight();
    if (m_rates.size() > 0)
    {
        for (int i = 0; i < m_rects.size() && i < m_datas.size(); i++)
        {
            PriceData2 pData = m_datas.get(i);
            FCRectF rect = pData.m_nowRect;// new FCRect(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
            if (!m_useAnimation)
            {
				FCRectF newRect = {m_rects.get(i).left, m_rects.get(i).top, m_rects.get(i).right, m_rects.get(i).bottom};
                rect = newRect;
            }
            Long backColor = FCColor_None;
            Long borderColor = FCColor_None;
			if (MyColor::getStyle() == 0)
            {
                if (pData.m_close >= pData.m_lastClose)
                {
					backColor = FCColor::rgb(219, 68, 83);
                }
                else
                {
					backColor = FCColor::rgb(15, 193, 118);
                }
				borderColor = FCColor::rgb(100, 100, 100);
            }
            else
            {
                if (pData.m_close >= pData.m_lastClose)
                {
					backColor = FCColor::rgb(255, 255, 255);
                }
                else
                {
					backColor = FCColor::rgb(255, 255, 255);
					borderColor = FCColor::rgb(255, 255, 255);
                }
            }
			FCPoint location = {rect.left, rect.top};
			FCSize size = {(int)(rect.right - rect.left), (int)(rect.bottom - rect.top)};
            paint->fillRect(backColor, location.x, location.y, location.x + size.cx, location.y + size.cy);
            paint->drawRect(borderColor, 1, 0, location.x, location.y, location.x + size.cx, location.y + size.cy);
            int fontSize1 = (int)(min(size.cx, size.cy) / 5);
            if (fontSize1 > 1)
            {
                String baseUpper = pData.m_text;
                FCFont font1(L"Default", fontSize1);
                FCSize tSize = paint->textSize(baseUpper, &font1);
                bool isContinue = false;
                while (tSize.cx > size.cx - 10)
                {
                    fontSize1 = fontSize1 - 1;
                    if (fontSize1 < 1)
                    {
                        isContinue = true;
                        break;
                    }
					FCFont newFont(L"Default", fontSize1);
                    font1 = newFont;
                    tSize = paint->textSize(baseUpper, &font1);
                }
                if (isContinue)
                {
                    continue;
                }
                String quoteUpper = pData.m_key;
                FCFont font2(L"Default", fontSize1 / 2);
                FCSize tSize2 = paint->textSize(quoteUpper, &font2);
				if (MyColor::getStyle() == 0)
                {
					FCDraw::drawText(paint, baseUpper, FCColor::rgb(255, 255, 255), &font1, location.x + (size.cx - tSize.cx) / 2, location.y + size.cy / 2 - tSize.cy - tSize.cy / 2);
					FCDraw::drawText(paint, quoteUpper, FCColor::rgb(255, 255, 255), &font2, location.x + (size.cx - tSize2.cx) / 2, location.y + size.cy / 2 - tSize.cy / 4);
                }
                else
                {
					FCDraw::drawText(paint, baseUpper, FCColor::rgb(0, 0, 0), &font1, location.x + (size.cx - tSize.cx) / 2, location.y + size.cy / 2 - tSize.cy - tSize.cy / 2);
					FCDraw::drawText(paint, quoteUpper, FCColor::rgb(0, 0, 0), &font2, location.x + (size.cx - tSize2.cx) / 2, location.y + size.cy / 2 - tSize.cy / 4);
                }
				String strPrice = L"0.00%";
				if(pData.m_lastClose > 0){
					strPrice = FCTran::getValueByDigit(100 * (pData.m_close - pData.m_lastClose) / pData.m_lastClose, 2) + L"%";
					if(pData.m_close > pData.m_lastClose){
						strPrice = String(L"+") + strPrice;
					}
				}
                FCFont font3(L"Default", fontSize1 * 2 / 3);
                FCSize tSize5 = paint->textSize(strPrice, &font3);
				if (MyColor::getStyle() == 0)
                {
					FCDraw::drawText(paint, strPrice, FCColor::rgb(255, 255, 255), &font3, location.x + (size.cx - tSize5.cx) / 2, location.y + size.cy / 2 + tSize.cy - tSize.cy / 2);
                }
                else
                {
					FCDraw::drawText(paint, strPrice, FCColor::rgb(0, 0, 0), &font3, location.x + (size.cx - tSize5.cx) / 2, location.y + size.cy / 2 + tSize.cy - tSize.cy / 2);
                }
            }
        }
    }
}

void PyrometerDiv::onSizeChanged(){
    updatePyromoter();
    FCDiv::onSizeChanged();
}

void PyrometerDiv::updatePyromoter(){
    m_rates.clear();
    std::vector<PriceData2> priceDatasCopy;
    for (int i = 0; i < m_datas.size(); i++)
    {
        priceDatasCopy.push_back(m_datas.get(i));
    }
    sort(priceDatasCopy.begin(), priceDatasCopy.end(), PriceDataCompare);
    m_datas.clear();
    for (int i = 0; i < priceDatasCopy.size(); i++)
    {
        m_datas.add(priceDatasCopy[i]);
    }
    //m_datas.Sort(new PriceDataCompare());
    double totalAmount = 0;
    for (int i = 0; i < m_datas.size(); i++)
    {
        totalAmount += m_datas.get(i).m_value;
    }
    for (int i = 0; i < m_datas.size(); i++)
    {
        m_rates.add(m_datas.get(i).m_value / totalAmount);
    }
    m_rects.clear();
    Rwidth = getWIDTH();
    Rheight = getHEIGHT();
    ArrayList<double> areas;
    for (int i = 0; i < m_rates.size(); i++)
    {
        areas.add(m_rates.get(i) * getWIDTH() * getHEIGHT());
    }
    ArrayList<double> children = areas;
    ArrayList<double> row;
    double w = FCTran::minValue(Rwidth, Rheight);
    while (true)
    {
        if (w <= 0) break;
        if (children.size() == 0)
        {
            if (row.size() > 0)
            {
                layoutrow(row, w);  
            }
            break;
        }

        double c = children.get(0);
        if (c == 0)
        {
            layoutrow(row, w);
            break;
        }
        ArrayList<double> newrow;  
        for(int x = 0; x < row.size(); x++){
            newrow.add(row.get(x));
        }
        newrow.add(c);

        if (worst(row, w) >= worst(newrow, w))
        {  
            ArrayList<double> tmp;
            for (int x = 1; x < children.size(); x++)
            {
                tmp.add(children.get(x));
            }
            children = tmp;
            row = newrow;
        }
        else
        {  
            layoutrow(row, w);  
            row.clear();
            w = width(row, (int)w);
        }
    }
}
